﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Core.Mgr._Timer
{
    /// <summary>
    /// 计时器管理器（基于协程）
    /// </summary>
    public static class TimerMgr
    {
        private static int _timerId = 0;
        private static Dictionary<int, Coroutine> timerCoroutines = new Dictionary<int, Coroutine>();

        /// <summary>
        /// 启动计时器
        /// </summary>
        /// <param name="callBack">计时器事件</param>
        /// <param name="delay">调用延迟</param>
        /// <param name="doTimes">调用次数，-1表示无限循环</param>
        /// <param name="repeatInterval">调用间隔</param>
        /// <returns>Timer Id</returns>
        public static int StartTimer(Action callBack, float delay = 0, int doTimes = 1, float repeatInterval = 1)
        {
            _timerId++;
            int curTimerId = _timerId;
            var coroutine = GameRoot.Ins.StartCoroutine(TimeCoroutine(curTimerId, callBack, delay, doTimes,
                repeatInterval));
            //添加进字典
            timerCoroutines.Add(curTimerId, coroutine);
            return curTimerId;
        }

        /// <summary>
        /// 手动结束计时器
        /// </summary>
        public static void EndTimer(int timerId)
        {
            //如果字典中存在指定Key值存在元素
            if (timerCoroutines.TryGetValue(timerId, out var coroutine))
            {
                if (GameRoot.Ins != null)
                {
                    //停止协程
                    GameRoot.Ins.StopCoroutine(coroutine);
                    //移除
                    timerCoroutines.Remove(timerId);
                }
            }
        }

        private static IEnumerator TimeCoroutine(int timerId, Action callBack, float delay = 0f, int doTimes = 1,
            float repeatInterval = 1f)
        {
            //标记
            float timeTick = repeatInterval;
            //标记
            int finishCount = 0;
            //
            bool isLoop = doTimes == -1;
            //延迟执行
            yield return new WaitForSeconds(delay);

            //是否循环
            if (isLoop)
            {
                //一直执行
                while (true)
                {
                    //第一次一定会执行，之后每隔"标记"的时间执行一次
                    if (timeTick >= repeatInterval)
                    {
                        //回调
                        callBack?.Invoke();
                        //从新开始计时
                        timeTick = 0f;
                    }

                    //开始计时
                    timeTick += Time.deltaTime;
                    yield return null;
                }
            }
            else
            {
                //“标记”次数小于调用次数一直循环
                while (finishCount < doTimes)
                {
                    //如果时间大于时间间隔则执行
                    if (timeTick >= repeatInterval)
                    {
                        //回调
                        callBack?.Invoke();
                        //从新开始计时
                        timeTick = 0f;
                        //"标记" ++
                        finishCount++;
                    }

                    //开始计时
                    timeTick += Time.deltaTime;
                    yield return null;
                }
            }

            //手动结束
            EndTimer(timerId);
        }
    }
}